package com.lytfly.flowable.modules.flow.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.lytfly.flowable.domain.*;
import com.lytfly.flowable.entity.Personal;
import com.lytfly.flowable.modules.flow.entity.FlowCommentInfo;
import com.lytfly.flowable.modules.flow.entity.FlowExtendHisprocinst;
import com.lytfly.flowable.modules.flow.entity.FlowExtendProcinst;
import com.lytfly.flowable.modules.flow.mapper.IFlowableProcessInstanceMapper;
import com.lytfly.flowable.modules.flow.service.BaseProcessService;
import com.lytfly.flowable.modules.flow.service.IFlowExtendProcinstService;
import com.lytfly.flowable.modules.flow.service.IFlowableProcessInstanceService;
import com.lytfly.flowable.modules.flow.service.IBpmnModelService;
import com.lytfly.flowable.service.IPersonalService;
import com.lytfly.flowable.utils.DurationUtils;
import com.lytfly.flowable.utils.ElUtil;
import lombok.extern.slf4j.Slf4j;
import org.flowable.bpmn.constants.BpmnXMLConstants;
import org.flowable.bpmn.model.*;
import org.flowable.common.engine.api.FlowableException;
import org.flowable.common.engine.impl.util.IoUtil;
import org.flowable.engine.*;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.Execution;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.identitylink.api.IdentityLink;
import org.flowable.image.ProcessDiagramGenerator;
import org.flowable.image.impl.DefaultProcessDiagramGenerator;
import org.flowable.task.api.Task;
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @program: flow
 * @description: 流程实例service实现类
 * @author: Bruce.Liu
 * @create: 2021-04-20 14:47
 **/
@Slf4j
@Service
public class FlowableProcessInstanceServiceImpl extends BaseProcessService implements IFlowableProcessInstanceService {

    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private HistoryService historyService;
    @Autowired
    private IPersonalService personalService;
    @Autowired
    private ObjectMapper objectMapper;
    @Autowired
    private IBpmnModelService bpmnModelService;
    @Autowired
    private IdentityService identityService;
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private IFlowExtendProcinstService extendProcinstService;
    @Autowired
    private IFlowableProcessInstanceMapper flowableProcessInstanceMapper;
    @Autowired
    private TaskService taskService;

    @Qualifier("processEngine")
    @Resource
    protected ProcessEngine processEngine;

    /**
     * 拒绝(终止流程)
     *
     * @param endVO 基本参数
     * @return
     */
    @Override
    public void stopProcess(EndVO endVO) {
        endVO.setCommentTypeEnum(CommentTypeEnum.LCZZ);
        endVO.setProcessStatusEnum(ProcessStatusEnum.ZZ);
        TaskEntity taskEntity = (TaskEntity) taskService.createTaskQuery()
                .taskId(endVO.getTaskId())
                .singleResult();
        assert taskEntity != null;
        String taskDefinitionKey = taskEntity.getTaskDefinitionKey();
        String processDefinitionId = taskEntity.getProcessDefinitionId();
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                .processInstanceId(endVO.getProcessInstanceId())
                .singleResult();
        if (processInstance == null) {
            throw new FlowableException("流程实例不存在,请联系管理员!");
        }
        if (processInstance.isSuspended()) {
            throw new FlowableException("流程实例已挂起,请联系管理员!");
        }
        //查询流程实例的子实例
        ProcessInstance subProcessInstance = runtimeService.createProcessInstanceQuery()
                .superProcessInstanceId(endVO.getProcessInstanceId())
                .singleResult();
        List<EndEvent> endActivityList = null;
        //查询结束节点
        if (subProcessInstance != null) {
            endActivityList = bpmnModelService.findEndFlowElement(subProcessInstance.getProcessDefinitionId());
        } else {
            endActivityList = bpmnModelService.findEndFlowElement(processInstance.getProcessDefinitionId());
        }
        if (CollUtil.isNotEmpty(endActivityList)) {
            //这里找到任意一个结束节点就可以
            String endNodeId = endActivityList.get(0).getId();
            List<String> allExecutionIdList = new ArrayList<>();
            if (bpmnModelService.isChildProcessNodeByActivityId(processDefinitionId, endNodeId)
                    && bpmnModelService.isChildProcessNodeByActivityId(processDefinitionId, taskDefinitionKey)) {
                Execution executionTask = runtimeService.createExecutionQuery()
                        .executionId(taskEntity.getExecutionId())
                        .singleResult();
                String parentId = executionTask.getParentId();
                List<Execution> childExecutionList = runtimeService.createExecutionQuery().parentId(parentId).list();
                childExecutionList.forEach(execution -> allExecutionIdList.add(execution.getId()));
            } else {
                List<Execution> childExecutionList = runtimeService.createExecutionQuery().parentId(taskEntity.getProcessInstanceId()).list();
                childExecutionList.forEach(execution -> allExecutionIdList.add(execution.getId()));
            }
            this.moveExecutionsToSingleActivityId(allExecutionIdList, endNodeId);
            this.evictHighLightedNodeCache(taskEntity.getProcessInstanceId());
            this.evictOneActivityVoCache(taskEntity.getProcessInstanceId(), taskDefinitionKey);
        }
        //设置在哪个节点结束的
        endVO.setActivityId(taskDefinitionKey);
        endVO.setActivityName(taskEntity.getName());
        this.addFlowCommentInfoAndProcessStatus(endVO);
        log.info("流程ID:{},已停止", processInstance.getProcessInstanceId());
    }

    /**
     * 查询我发起的流程列表
     *
     * @param paramsVO 查询参数
     * @param query    查询参数
     * @return
     * @throws Exception
     */
    @Override
    public List<ProcessInstanceVO> findMyProcessInstanceByPage(InstanceQueryParamsVO paramsVO, Query query) {
        IPage<ProcessInstanceVO> queryPage = new Page<>(query.getPageNum(), query.getPageSize());
        IPage<ProcessInstanceVO> page = flowableProcessInstanceMapper.findMyProcessinstancesPagerModel(queryPage, paramsVO);
        List<ProcessInstanceVO> processInstanceVOList = page.getRecords();
        this.setMyProcessInstanceDataList(processInstanceVOList);
        return processInstanceVOList;
    }

    /**
     * 为流程设置详细数据
     *
     * @param processInstanceVOList
     */
    private void setMyProcessInstanceDataList(List<ProcessInstanceVO> processInstanceVOList) {
        if (CollUtil.isNotEmpty(processInstanceVOList)) {
            processInstanceVOList.forEach(itemVO -> {
                itemVO.setProcessStatusName(ProcessStatusEnum.getEnumMsgByType(itemVO.getProcessStatus()));
                Date startTime = itemVO.getStartTime();
                Date endTime = itemVO.getEndTime();
                if (itemVO.getEndTime() == null) {
                    List<Task> list = taskService.createTaskQuery().processInstanceId(itemVO.getProcessInstanceId()).list();
                    List<String> userCodeList = new ArrayList<>();
                    List<String> roleGroupCodeList = new ArrayList<>();
                    if (CollUtil.isNotEmpty(list)) {
                        list.forEach(task -> {
                            if (StrUtil.isNotBlank(task.getAssignee())) {
                                userCodeList.add(task.getAssignee());
                            }
                            List<IdentityLink> identityLinksForTask = taskService.getIdentityLinksForTask(task.getId());
                            if (CollUtil.isNotEmpty(identityLinksForTask)) {
                                identityLinksForTask.forEach(identityLink -> {
                                    String userCode = identityLink.getUserId();
                                    String roleGroupCode = identityLink.getGroupId();
                                    if (StrUtil.isNotBlank(userCode)) {
                                        userCodeList.add(userCode);
                                    }
                                    if (StrUtil.isNotBlank(roleGroupCode)) {
                                        roleGroupCodeList.add(roleGroupCode);
                                    }
                                });
                            }
                        });
                    }
                    List<Personal> personals = new ArrayList<>();
                    if (CollUtil.isNotEmpty(userCodeList)) {
                        List<Personal> ps = personalService.getPersonalsByCodeList(userCodeList);
                        personals.addAll(ps);
                    }
                    if (CollUtil.isNotEmpty(roleGroupCodeList)) {
                        List<Personal> rs = personalService.getPersonalsByRoleGroupCodeList(roleGroupCodeList);
                        personals.addAll(rs);
                    }
                    List<ApproverVO> approverVOList = new ArrayList<>();
                    if (CollUtil.isNotEmpty(personals)) {
                        personals.forEach(personal ->
                                approverVOList.add(new ApproverVO(ApproverVO.USER, personal.getCode(), personal.getName(), personal.getMobile()))
                        );
                    }
                    itemVO.setCurrentAssignees(approverVOList);
                    endTime = new Date();
                }
                long duration = endTime.getTime() - startTime.getTime();
                itemVO.setTotalTime(DurationUtils.getDuration(duration));
            });
        }
    }

    /**
     * 启动流程
     *
     * @param params 启动参数
     * @return
     */
    @Override
    public ProcessInstance startProcessInstanceByKey(StartProcessInstanceVO params) {
        String processDefinitionKey = params.getProcessDefinitionKey();
        String businessKey = params.getBusinessKey();
        if (StrUtil.isNotBlank(processDefinitionKey) && StrUtil.isNotBlank(businessKey)) {
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                    .processDefinitionKey(processDefinitionKey)
                    .latestVersion()
                    .singleResult();
            if (processDefinition == null) {
                throw new FlowableException("流程定义不存在,请联系系统管理员!");
            }
            if (processDefinition.isSuspended()) {
                throw new FlowableException("此流程已经挂起,请联系系统管理员!");
            }
            //流程提交人
            String creator = params.getCreator();
            String currentUserCode = params.getCurrentUserCode();
            if (StrUtil.isBlank(creator) && StrUtil.isNotBlank(currentUserCode)) {
                creator = currentUserCode;
                params.setCreator(creator);
            }
            if (StrUtil.isNotBlank(creator) && StrUtil.isBlank(currentUserCode)) {
                currentUserCode = creator;
                params.setCurrentUserCode(creator);
            }
            Personal personal = personalService.getPersonalByCode(currentUserCode);
            if (personal == null) {
                throw new FlowableException("工号为：" + currentUserCode + "的当前发起人用户匹配不到，请确认!");
            } else {
                if (StrUtil.isBlank(params.getDeptId())) {
                    params.setDeptId(personal.getDeptId());
                }
            }
            //此处很关键,设置变量需要考虑诸多因素
            this.getStartVariables(params, personal);
            //验证变量设置
            this.validProcessInstanceVar(params);
            identityService.setAuthenticatedUserId(creator);
            ProcessInstance processInstance = runtimeService.createProcessInstanceBuilder()
                    .processDefinitionId(processDefinition.getId())
                    .name(params.getFormName().trim())
                    .businessKey(businessKey.trim())
                    .variables(params.getVariables())
                    .tenantId(params.getAppSn().trim())
                    .start();
            identityService.setAuthenticatedUserId(null);
            //保存扩展流程实例信息
            this.createExtendProcinst(params, processInstance, creator);
            //保存审核意见
            String processInstanceId = processInstance.getProcessInstanceId();
            FlowCommentInfo commentInfo = new FlowCommentInfo(CommentTypeEnum.TJ.name(), creator,
                    processInstanceId,
                    CommentTypeEnum.TJ.getName());
            BpmnModel bpmnModel = bpmnModelService.getBpmnModelByProcessDefId(processInstance.getProcessDefinitionId());
            StartEvent start = bpmnModelService.findStartFlowElement(bpmnModel.getMainProcess());
            if (start != null) {
                commentInfo.setActivityId(start.getId());
                commentInfo.setActivityName(start.getName());
            }
            this.addFlowCommentInfo(commentInfo);
            log.info("流程ID:{},已启动", processInstance.getProcessInstanceId());
            return processInstance;
        } else {
            throw new FlowableException("启动流程的参数不存在");
        }
    }


    /**
     * 创建流程实例扩展表信息
     *
     * @param params          启动参数
     * @param processInstance 流程实例对象
     * @param creator         创建人
     * @throws Exception
     */
    private void createExtendProcinst(StartProcessInstanceVO params, ProcessInstance processInstance, String creator) {
        FlowExtendProcinst extendProcinst = new FlowExtendProcinst();
        extendProcinst.setCurrentUserCode(params.getCurrentUserCode());
        extendProcinst.setProcessInstanceId(processInstance.getId());
        extendProcinst.setProcessDefinitionId(processInstance.getProcessDefinitionId());
        extendProcinst.setProcessStatus(ProcessStatusEnum.SPZ.toString());
        extendProcinst.setProcessName(params.getFormName());
        extendProcinst.setModelKey(params.getProcessDefinitionKey());
        extendProcinst.setBusinessKey(params.getBusinessKey());
        extendProcinst.setTenantId(params.getAppSn());
        extendProcinst.setCurrentUserCode(params.getCurrentUserCode());
        extendProcinst.setCreator(creator);
        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
                .processInstanceId(processInstance.getProcessInstanceId())
                .singleResult();
        if (historicProcessInstance.getEndTime() != null) {
            extendProcinst.setProcessStatus(ProcessStatusEnum.BJ.toString());
            extendProcinst.setProcessName(params.getFormName());
            extendProcinst.setBusinessKey(params.getBusinessKey());
            extendProcinst.setProcessDefinitionId(historicProcessInstance.getProcessDefinitionId());
            extendProcinst.setModelKey(params.getProcessDefinitionKey());
            extendProcinst.setTenantId(params.getAppSn());
            extendProcinst.setCurrentUserCode(params.getCurrentUserCode());
            extendProcinst.setId(IdWorker.get32UUID());
            FlowExtendHisprocinst extendHisprocinst = new FlowExtendHisprocinst();
            BeanUtils.copyProperties(extendProcinst, extendHisprocinst);
            extendHisprocinst.insert();
        } else {
            extendProcinstService.saveExtendProcinstAndHis(extendProcinst);
        }
    }

    /**
     * 判断条件参数是否设置过
     *
     * @param params 参数
     * @return
     */
    private void validProcessInstanceVar(StartProcessInstanceVO params) {
        ProcessDefinition lastProcessDefinition = repositoryService.createProcessDefinitionQuery()
                .latestVersion()
                .processDefinitionKey(StrUtil.trim(params.getProcessDefinitionKey()))
                .singleResult();
        if (lastProcessDefinition == null) {
            String errorMessage = "【" + params.getProcessDefinitionKey() + "】流程定义未找到！";
            log.error(errorMessage);
            throw new RuntimeException(errorMessage);
        }
        //根据流程定义id或者所有的task
        List<UserTask> userTaskDataList = bpmnModelService.findUserTasksByProcessDefId(lastProcessDefinition.getId());
        //保存包含uel表达式的task
        List<UserTask> containUelUserTaskList = new ArrayList<>();
        if (CollUtil.isNotEmpty(userTaskDataList)) {
            containUelUserTaskList = userTaskDataList.stream()
                    .filter(userTask -> StrUtil.containsIgnoreCase(userTask.getAssignee(), "${"))
                    .collect(Collectors.toList());
        }
        //保存包含uel表达式的变量
        List<String> uelStrList = new ArrayList<>();
        containUelUserTaskList.forEach(userTask -> {
            if (userTask.getLoopCharacteristics() != null) {
                String inputDataItem = userTask.getLoopCharacteristics().getInputDataItem();
                if (StrUtil.isNotBlank(inputDataItem)) {
                    uelStrList.add(inputDataItem);
                }
            } else {
                uelStrList.add(userTask.getAssignee());
            }

        });
        //获取设置的变量map
        Map<String, Object> variables = params.getVariables();
        Map<String, String> keys = new HashMap<>(6);
        variables.forEach((k, v) -> {
            if (v instanceof String) {
                keys.put(k, k);
            } else if (v instanceof ObjectNode) {
                ObjectNode node = (ObjectNode) v;
                Iterator<String> nodeKeys = node.fieldNames();
                while (nodeKeys.hasNext()) {
                    String nodeKey = nodeKeys.next();
                    String tempNodeKey = k + "." + nodeKey;
                    String enumMsg = StartVariableEnum.getEnumMsgByCode(nodeKey);
                    keys.put(tempNodeKey, enumMsg);
                }
            } else if (v instanceof Collection) {
                keys.put(k, k);
            }
        });
        for (String assigneeUel : uelStrList) {
            if (StrUtil.isNotBlank(assigneeUel)) {
                String assignee = ElUtil.getOriginalValue(assigneeUel);
                if (!keys.containsKey(assignee)) {
                    String code = ElUtil.getSpotValue(assignee);
                    String enumMsg = StartVariableEnum.getEnumMsgByCode(code);
                    if (StrUtil.isNotBlank(code)) {
                        throw new FlowableException(enumMsg + "的参数没有设置,请联系管理员!");
                    }
                    break;
                }
            }
        }
    }

    @Override
    public Map<String, Object> getStartVariables(StartProcessInstanceVO params, Personal personal) {
        Map<String, Object> variables = null;
        if (params.getVariables() == null) {
            variables = new HashMap<>(2);
            params.setVariables(variables);
        } else {
            final String formCode = "form";
            Map<String, Object> formMap = params.getVariables();
            if (!formMap.containsKey(formCode)) {
                ObjectNode formNode = objectMapper.createObjectNode();
                Map<String, Object> listMap = new HashMap<>(10);
                if (MapUtil.isNotEmpty(formMap)) {
                    formMap.forEach((k, v) -> {
                        if (v instanceof List) {
                            String key = formCode + "_" + k;
                            listMap.put(key, v);
                        } else if (v instanceof String) {
                            formNode.put(k, String.valueOf(v));
                        } else if (v instanceof Integer) {
                            formNode.put(k, Integer.valueOf(v + ""));
                        } else if (v instanceof Float) {
                            formNode.put(k, Float.valueOf(v + ""));
                        } else if (v instanceof Double) {
                            formNode.put(k, Double.valueOf(v + ""));
                        } else if (v instanceof Long) {
                            formNode.put(k, Long.valueOf(v + ""));
                        } else if (v instanceof BigDecimal) {
                            formNode.put(k, new BigDecimal(v + ""));
                        } else {
                            String str = String.valueOf(v);
                            if (str.startsWith("0")) {
                                formNode.put(k, str);
                            } else {
                                formNode.putPOJO(k, v);
                            }
                        }
                    });
                }
                formMap = new HashMap<>(2);
                params.setVariables(formMap);
                params.getVariables().put(formCode, formNode);
                if (MapUtil.isNotEmpty(listMap)) {
                    listMap.forEach((k, v) -> params.getVariables().put(k, v));
                }
            }
            //提交人未设置时自动跳过
            params.getVariables().put(FlowConstant.FLOW_SUBMITTER_VAR, "");
            params.getVariables().put(FlowConstant.FLOWABLE_SKIP_EXPRESSION_ENABLED, true);
            if (StrUtil.isBlank(params.getDeptId())) {
                params.setDeptId(personal.getDeptId());
            }
            variables = params.getVariables();
        }
        return variables;
    }

    @Override
    public void revokeProcess(RevokeProcessVO revokeVO) {
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                .processInstanceId(revokeVO.getProcessInstanceId()).singleResult();
        assert processInstance != null;
        //1.添加撤回意见
        FlowCommentInfo commentInfo = new FlowCommentInfo(CommentTypeEnum.CH.toString(), revokeVO.getUserCode(),
                revokeVO.getProcessInstanceId(),
                revokeVO.getMessage());
        this.addFlowCommentInfo(commentInfo);
        log.info("流程撤回意见:{}", commentInfo);
        //2.设置提交人
        runtimeService.setVariable(revokeVO.getProcessInstanceId(), FlowConstant.FLOW_SUBMITTER_VAR, processInstance.getStartUserId());
        //3.执行撤回
        Activity disActivity = bpmnModelService.findActivityByName(processInstance.getProcessDefinitionId(), FlowConstant.FLOW_SUBMITTER);
        //4.删除运行和历史的节点信息
        this.deleteActivity(disActivity.getId(), revokeVO.getProcessInstanceId());
        //5.执行跳转
        List<Execution> executions = runtimeService.createExecutionQuery().parentId(revokeVO.getProcessInstanceId()).list();
        List<String> executionIds = new ArrayList<>();
        executions.forEach(execution -> executionIds.add(execution.getId()));
        this.moveExecutionsToSingleActivityId(executionIds, disActivity.getId());
        log.info("流程ID:{},已撤回", processInstance.getProcessInstanceId());
    }

    @Override
    public void suspendOrActivateProcessInstanceById(String processInstanceId, Integer suspensionState) {
        final int activeStatus = 1;
        final int suspendStatus = 2;
        if (suspensionState == activeStatus) {
            runtimeService.suspendProcessInstanceById(processInstanceId);
            log.info("流程ID:{},已挂起", processInstanceId);
        } else if (suspensionState == suspendStatus) {
            runtimeService.activateProcessInstanceById(processInstanceId);
            log.info("流程ID:{},已挂起", processInstanceId);
        } else {
            throw new FlowableException("参数异常");
        }
    }

    @Override
    public byte[] createProcessInstanceImage(String processInstanceId) {
        //1.获取当前的流程实例
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        String processDefinitionId = null;
        List<String> activeActivityIds = new ArrayList<>();
        List<String> highLightedFlows = new ArrayList<>();
        //2.获取所有的历史轨迹线对象
        List<HistoricActivityInstance> historicSquenceFlows = historyService.createHistoricActivityInstanceQuery()
                .processInstanceId(processInstanceId).activityType(BpmnXMLConstants.ELEMENT_SEQUENCE_FLOW).list();
        historicSquenceFlows.forEach(historicActivityInstance -> highLightedFlows.add(historicActivityInstance.getActivityId()));
        //3. 获取流程定义id和高亮的节点id
        if (processInstance != null) {
            //3.1. 正在运行的流程实例
            processDefinitionId = processInstance.getProcessDefinitionId();
            activeActivityIds = runtimeService.getActiveActivityIds(processInstanceId);
        } else {
            //3.2. 已经结束的流程实例
            HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
            processDefinitionId = historicProcessInstance.getProcessDefinitionId();
            //3.3. 获取结束节点列表
            List<HistoricActivityInstance> historicEnds = historyService.createHistoricActivityInstanceQuery()
                    .processInstanceId(processInstanceId).activityType(BpmnXMLConstants.ELEMENT_EVENT_END).list();
            List<String> finalActiveActivityIds = activeActivityIds;
            historicEnds.forEach(historicActivityInstance -> finalActiveActivityIds.add(historicActivityInstance.getActivityId()));
        }
        //4. 获取bpmnModel对象
        BpmnModel bpmnModel = bpmnModelService.getBpmnModelByProcessDefId(processDefinitionId);
        //5. 生成图片流
        ProcessDiagramGenerator diagramGenerator = new DefaultProcessDiagramGenerator();
        ProcessEngineConfiguration configuration = processEngine.getProcessEngineConfiguration();
        InputStream inputStream = diagramGenerator.generateDiagram(bpmnModel, "png", activeActivityIds, highLightedFlows, configuration.getActivityFontName(),
                configuration.getLabelFontName(), configuration.getAnnotationFontName(), configuration.getClassLoader(), 1.0, true);
        //6. 转化成byte便于网络传输
        return IoUtil.readInputStream(inputStream, "image inputStream name");
    }
}
